home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume9 / draw_jt / part02 < prev    next >
Encoding:
Text File  |  1989-12-12  |  51.3 KB  |  2,135 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v09i062: draw, part 02/02
  4. Reply-To: jta@sah.vtt.fi (Juha Takala)
  5.  
  6. Posting-number: Volume 9, Issue 62
  7. Submitted-by: jta@sah.vtt.fi (Juha Takala)
  8. Archive-name: draw_jt/part02
  9.  
  10. [This is "dr_lib", a library to produce plots in various formats including
  11. plot(3) and HPGL formats, and "draw", a simple front-end for the library.
  12. See the README for more information.  ++bsa]
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 2 (of 2)."
  21. # Contents:  dr_lib.c draw.c
  22. # Wrapped by allbery@uunet on Tue Dec 12 21:15:58 1989
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'dr_lib.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'dr_lib.c'\"
  26. else
  27. echo shar: Extracting \"'dr_lib.c'\" \(31312 characters\)
  28. sed "s/^X//" >'dr_lib.c' <<'END_OF_FILE'
  29. X/*
  30. X
  31. XCopyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
  32. X
  33. X     This program is free software; you can redistribute it and/or modify
  34. X     it under the terms of the GNU General Public License as published by
  35. X     the Free Software Foundation; version 1.
  36. X
  37. X     This program is distributed in the hope that it will be useful,
  38. X     but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. X     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40. X     the file "License" for more details
  41. X
  42. X     You should have received a copy of the GNU General Public License
  43. X     along with this program; if not, write to the Free Software
  44. X     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  45. X
  46. X
  47. X */
  48. X
  49. X
  50. X/* Description:
  51. X *  dr_lib.c provides interface between device level and my draw(1).
  52. X *  Supported devices are:
  53. X *  - hpgl output for hp7475 plotter
  54. X *  - gl_plot(3) calls for EGA or matrix printer output
  55. X *  - plot(3) interface
  56. X *
  57. X */
  58. Xstatic char *rcsid =
  59. X  "$Id: dr_lib.c,v 2.4 89/12/08 14:00:34 jta Exp Locker: jta $";
  60. X
  61. X/* define this, if your plotter connection is 'y-cable' (not direct) */
  62. X/* #define YCABLE            /*  */
  63. X
  64. X/* definede this if you want to ask paper size from plotter */
  65. X/* (should not be used, if you are going to use this package as */
  66. X/* part of pipelines) */
  67. X/* #define ASK            /*  */
  68. X
  69. X#include <stdio.h> 
  70. X#include <math.h>
  71. X#ifdef MSDOS
  72. X#include <bios.h>
  73. X#endif
  74. X#include "dr_lib.h"
  75. X
  76. X#define  ESC 0x1b        /* ascii <ESC> */
  77. X
  78. Xstatic int xscale(), yscale();
  79. Xstatic void sends(), invdev();
  80. X
  81. X#ifdef ASK
  82. Xstatic void takes();
  83. X#endif /* ASK */
  84. X
  85. X/*
  86. X * internal global variable declarations
  87. X *
  88. X */
  89. X                /* coordinate transformations */
  90. Xstatic float xuserincr,   yuserincr;
  91. Xstatic float xuserlow,    yuserlow;
  92. Xstatic float xuserhigh,   yuserhigh;
  93. Xstatic float xdevicelow,  ydevicelow;
  94. Xstatic float xdevicehigh, ydevicehigh;
  95. Xstatic float xrelarea,    yrelarea;
  96. Xstatic float xfactor,     yfactor;
  97. Xstatic float shape_factor, size_factor;    /* text 'fatness' and size factors */
  98. Xstatic int lastx=0, lasty=0;    /* device coordinates for last point */
  99. X
  100. X
  101. Xstatic int device = INVDEV;    /* what output device we are working for */
  102. Xstatic int old_linetype = -1;    /* remember last used linetype */
  103. Xstatic int old_pen = -1;    /* ...and pen */
  104. X
  105. Xstatic int errcount, warncount, errfile;
  106. Xstatic char *errfilename = "draw.err";
  107. X
  108. Xstatic FILE *errfilefp;
  109. X
  110. X
  111. X
  112. X/* ********************************************************** */
  113. X/*                                                            */
  114. X/* Following functions are ment to be subroutines to be       */
  115. X/* called from a user supplied main program                   */
  116. X/*                                                            */
  117. X/* ********************************************************** */
  118. X
  119. X/*
  120. X * dr_set_cset()   - select cset
  121. X *
  122. X */
  123. Xvoid dr_set_cset(n)
  124. Xint n;
  125. X{
  126. X    char s[50];
  127. X
  128. X    switch (device)
  129. X      {
  130. X      case HP7475:
  131. X      if (n < 0 || n == 5 || (n > 9 && n < 30) || n > 39) {
  132. X          (void)sprintf(s, "Invalid cset code %d, using 0", n);
  133. X          dr_errmsg(s);
  134. X          n = 0;
  135. X      }
  136. X      (void)sprintf(s, "CS%d;\n", n);
  137. X      sends(s);
  138. X      break;
  139. X#ifdef GL_LIB
  140. X      case SCREEN:
  141. X/*      (void)sprintf(s, "cset not yet for SCREEN");
  142. X      dr_errmsg(s);        /*  */
  143. X      break;
  144. X#endif
  145. X#ifdef PLOT
  146. X      case PLOTLIB:
  147. X/*      (void)sprintf(s, "cset not valid for PLOT");
  148. X      dr_errmsg(s);        /*  */
  149. X      break;
  150. X#endif
  151. X      default:
  152. X      invdev(); break;
  153. X      }
  154. X}
  155. X
  156. X/*
  157. X * dr_set_pen()   - select pen
  158. X *
  159. X */
  160. Xvoid dr_set_pen(n)
  161. Xint n;                /* pen number, 1..6, 0=='put it away' */
  162. X{
  163. X    char s[50];
  164. X
  165. X    switch (device)
  166. X      {
  167. X      case HP7475:
  168. X      if (n < 0 || n > 6) {
  169. X          (void)sprintf(s, "Invalid pen code %d, using 1", n);
  170. X          dr_errmsg(s);
  171. X          n = 1;
  172. X      }
  173. X      if (n != old_pen) {    /* optimize for hpgl... */
  174. X          old_pen = n;
  175. X          (void)sprintf(s, "SP%d;", n);
  176. X          sends(s);
  177. X      }
  178. X      break;
  179. X#ifdef GL_LIB
  180. X      case SCREEN:
  181. X/*      (void)sprintf(s, "dr_set_pen(colour) not yet for SCREEN\n");
  182. X      dr_errmsg(s);        /*  */
  183. X      break;
  184. X#endif
  185. X#ifdef PLOT
  186. X      case PLOTLIB:
  187. X/*      (void)sprintf(s, "dr_set_pen(colour) not valid for PLOT\n");
  188. X      dr_errmsg(s);        /*  */
  189. X      break;
  190. X#endif
  191. X      default:
  192. X      invdev(); break;
  193. X      }
  194. X}
  195. X
  196. X/*
  197. X * dr_goto()  - move pen to point x, y
  198. X *
  199. X */
  200. Xvoid dr_goto(x, y, penup)
  201. Xfloat x, y;            /* where he wants to go */
  202. Xint penup;            /* nonzero == lift pen before moving */
  203. X{
  204. X    char s[60];
  205. X    lastx = xscale(x);
  206. X    lasty = yscale(y);
  207. X    switch (device)
  208. X      {
  209. X      case HP7475:
  210. X      if (penup) sends ("PU");
  211. X      else sends ("PA;PD");
  212. X          
  213. X      /* go to point, leave pen as told
  214. X       */
  215. X      (void)sprintf(s, "%d,%d;\n", lastx, lasty);
  216. X      sends(s);
  217. X      break;
  218. X#ifdef GL_LIB
  219. X      case SCREEN:
  220. X      if (penup)    n_movepen(lastx, lasty);
  221. X      else        n_draw(lastx, lasty);
  222. X      break;
  223. X#endif
  224. X#ifdef PLOT
  225. X      case PLOTLIB:
  226. X      if (penup)    move(lastx, lasty);
  227. X      else        cont(lastx, lasty);
  228. X      break;
  229. X#endif
  230. X      default:
  231. X      invdev(); break;
  232. X      }
  233. X    return;
  234. X}
  235. X
  236. X
  237. X/*
  238. X * dr_draw_line()  - draw line (x1,y1) .. (x2,y2)
  239. X *
  240. X * connect the two data points with line
  241. X */
  242. Xvoid dr_draw_line(x1, y1, x2, y2)
  243. Xfloat x1, y1, x2, y2;        /* data points */
  244. X{
  245. X    char s[60];
  246. X    
  247. X    lastx = xscale(x2);
  248. X    lasty = yscale(y2);
  249. X    switch (device)
  250. X      {
  251. X      case HP7475:
  252. X      /* lift pen,
  253. X       * go to first point,
  254. X       * drop pen there,
  255. X       */
  256. X      (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x1), yscale(y1));
  257. X      sends(s);
  258. X
  259. X      /* draw line segment, lift pen
  260. X       */
  261. X      (void)sprintf(s, "PD%d,%d;PU;\n", lastx, lasty);
  262. X      sends(s);
  263. X      break;
  264. X#ifdef GL_LIB
  265. X      case SCREEN:
  266. X      n_line(xscale(x1), yscale(y1), lastx, lasty);
  267. X      break;
  268. X#endif
  269. X#ifdef PLOT
  270. X      case PLOTLIB:
  271. X      line(xscale(x1), yscale(y1), lastx, lasty);
  272. X      break;
  273. X#endif
  274. X      default:
  275. X      invdev(); break;
  276. X      }
  277. X    return;
  278. X}
  279. X
  280. X
  281. X/*
  282. X * dr_draw_array()  - draw y = f(x)
  283. X *
  284. X * connect data points with line
  285. X */
  286. Xvoid dr_draw_array(x, y, n)
  287. Xfloat x[], y[];            /* data points */
  288. Xint n;                /* number of points in x[] and y[] */
  289. X{
  290. X    int i;
  291. X    char s[60];
  292. X    
  293. X    /* if we really have something to draw
  294. X     */
  295. X    if (n < 1)
  296. X      return;
  297. X
  298. X    switch (device)
  299. X      {
  300. X      case HP7475:
  301. X      /* lift pen,
  302. X       * go to first point,
  303. X       * drop pen there,
  304. X       */
  305. X      (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x[0]), yscale(y[0]));
  306. X      sends(s);
  307. X      
  308. X      /* draw line segments
  309. X       */
  310. X      for (i=1; i<n; i++) {
  311. X          if (i % 4 == 0) sends("\n");
  312. X          (void)sprintf(s, "PD%d,%d;", xscale(x[i]), yscale(y[i]));
  313. X          sends(s);
  314. X      }
  315. X      
  316. X      /* finally lift pen
  317. X       */
  318. X      sends("PU;\n");
  319. X      break;
  320. X#ifdef GL_LIB
  321. X      case SCREEN:
  322. X      n_movepen(xscale(x[0]), yscale(y[0]));
  323. X      for (i=1; i<n; i++)
  324. X        n_draw(xscale(x[i]), yscale(y[i]));
  325. X      break;
  326. X#endif
  327. X#ifdef PLOT
  328. X      case PLOTLIB:
  329. X      move(xscale(x[0]), yscale(y[0]));
  330. X      for (i=1; i<n; i++)
  331. X        cont(xscale(x[i]), yscale(y[i]));
  332. X      break;
  333. X#endif
  334. X      default:
  335. X      invdev(); break;
  336. X      }
  337. X    lastx = xscale(x[i-1]);
  338. X    lasty = yscale(y[i-1]);
  339. X    return;
  340. X}
  341. X
  342. X
  343. X/*
  344. X * dr_put_mark()  - make a mark at (x,y)
  345. X *
  346. X * put mark at data point
  347. X */
  348. Xvoid dr_put_mark(x, y, mark) 
  349. Xfloat x, y;            /* data point */
  350. Xchar mark;
  351. X{
  352. X    char s[60];
  353. X
  354. X    lastx = xscale(x);
  355. X    lasty = yscale(y);
  356. X    switch (device)
  357. X      {
  358. X      case HP7475:
  359. X      /* if we really have something to plot
  360. X       */
  361. X      
  362. X      /* lift pen,
  363. X       * set symbol mode,
  364. X       */
  365. X      (void)sprintf(s, "PA;PU;SM%c;", mark);
  366. X      sends(s);
  367. X      
  368. X      /* put symbol at all data points
  369. X       */
  370. X      (void)sprintf(s, "PU%d,%d;", lastx, lasty);
  371. X      sends(s);
  372. X      
  373. X      /* reset symbol mode
  374. X       */
  375. X      sends("SM;\n");
  376. X      break;
  377. X#ifdef GL_LIB
  378. X      case SCREEN:
  379. X      n_movepen(lastx, lasty);
  380. X      n_grafchar(mark);
  381. X      break;
  382. X#endif
  383. X#ifdef PLOT
  384. X      case PLOTLIB:
  385. X      move(lastx, lasty);
  386. X      *s = mark;
  387. X      *(s+1) = '\0';
  388. X      label(s);
  389. X      break;
  390. X#endif
  391. X      default:
  392. X      invdev(); break;
  393. X      }
  394. X    return;
  395. X}
  396. X
  397. X
  398. Xvoid dr_set_shape(x)
  399. Xfloat x;
  400. X{
  401. X    if (x > 0.0)
  402. X      shape_factor = x * xrelarea/yrelarea;
  403. X    return;
  404. X}
  405. X
  406. X
  407. Xvoid dr_set_size(x)
  408. Xfloat x;
  409. X{
  410. X    if (x > 0.0)
  411. X      size_factor = x;
  412. X    return;
  413. X}
  414. X
  415. X
  416. X/*
  417. X * dr_put_text()  - put some text
  418. X * plot(3) only has one size and orientation, what can you do!
  419. X *
  420. X */
  421. Xvoid dr_put_text(x, y, xofs, yofs, angle, size, s)
  422. Xfloat x, y;            /* where to put it */
  423. Xfloat xofs, yofs;        /* offset of start position, measured in */
  424. X                /* character size units */
  425. Xfloat angle;            /* radians, 0.0 == horizontal */
  426. Xfloat size;            /* relative size of text */
  427. Xchar *s;            /* the text */
  428. X{
  429. X    char ss[60];
  430. X    int senddir;
  431. X    char dir[30];
  432. X
  433. X    if (size <= 0.0) {
  434. X    sprintf(ss, "invalid size: %f");
  435. X    dr_errmsg(ss);
  436. X    return;
  437. X    }
  438. X    size *= size_factor;
  439. X
  440. X    switch (device)
  441. X      {
  442. X      case HP7475:
  443. X      senddir = (angle != 0.0);
  444. X      if (senddir) {
  445. X          if (angle == M_PI_2)
  446. X        sprintf(dir,"DI0,1");
  447. X          else if (angle == -M_PI_2)
  448. X        sprintf(dir,"DI0,-1");
  449. X          else
  450. X        sprintf(dir,"DI1,%f", tan(angle));
  451. X      }
  452. X
  453. X      /* lift pen, go to specified position, set direction & size,
  454. X       */
  455. X
  456. X      (void)sprintf(ss, "PA;PU%d,%d;%s;SR%4.2f,%4.2f;\n",
  457. X            xscale(x), yscale(y),
  458. X            (senddir ? dir : ""), 
  459. X            size * 0.75 * shape_factor * xrelarea,
  460. X            size * 1.5 * yrelarea);
  461. X      sends(ss);
  462. X
  463. X      /* go to offset,
  464. X       * put text,
  465. X       * restore 0 degree direction.
  466. X       */
  467. X      if ((xofs != 0.0) || (yofs != 0.0)) {
  468. X          (void)sprintf(ss, "CP%4.2f,%4.2f;\n", xofs, yofs);
  469. X          sends(ss);
  470. X      }
  471. X      sends("LB"); sends(s); sends("\03\n");
  472. X
  473. X      /* correction for y-offset, if necessary, to leave pen on same */
  474. X      /* height but after the text */
  475. X      if (yofs != 0.0) {
  476. X          (void)sprintf(ss, "CP0,%4.2f;\n", -yofs);
  477. X          sends(ss);
  478. X      }
  479. X
  480. X      if (senddir)
  481. X        sends("DI1,0;\n");
  482. X/*      lastx = ....;
  483. X      lasty = ....;        /* hp7475 does not really need these, */
  484. X                /* it remembers the pen position */
  485. X
  486. X      break;
  487. X#ifdef GL_LIB
  488. X      case SCREEN:
  489. X      n_movepen(xscale(x), yscale(y));
  490. X
  491. X#define GL_MODE_255_HAS_BUG
  492. X#ifdef GL_MODE_255_HAS_BUG
  493. X      /* DT Lewis!!  Wake up! */
  494. X      /* For some reason gl_lib works strangely with GL_MODE == 255 */
  495. X      /* (the output is  (almost) microscopic small and weird shape). */
  496. X      /* We can compensate that strangeness here by modifying size */
  497. X      /* and sape factors for g_fontctl()...  The values 3.0 and 0.4 */
  498. X      /* are experimental results (by kekkonen@sah.vtt.fi). */
  499. X      if (strncmp(getenv("GLMODE"),"256",3)==0)
  500. X        g_fontctl(3.0*size*yrelarea, 0.4*shape_factor, 1.0, angle, 0.0);
  501. X      else
  502. X#endif
  503. X#undef GL_MODE_255_HAS_BUG
  504. X        g_fontctl(size*yrelarea, shape_factor, 1.0, angle, 0.0);
  505. X      yofs = -0.5 - yofs;
  506. X      n_ch_ofs(xofs, yofs);
  507. X      n_grafstr(s);
  508. X      n_ch_ofs(0.0, -yofs);
  509. X      g_fontctl(size, 1.0, 1.0, 0.0, 0.0);
  510. X/*      lastx = ....;
  511. X      lasty = ....;        /* this does not really need these, */
  512. X                /* it remembers the pen position */
  513. X
  514. X      break;
  515. X#endif
  516. X#ifdef PLOT
  517. X#define PLOT_CH_XSIZE 70
  518. X#define PLOT_CH_YSIZE 100
  519. X      case PLOTLIB:
  520. X      {
  521. X          int i;
  522. X          float xsize, ysize;
  523. X          float xbase, ybase;
  524. X          float xincr, yincr;
  525. X          float xofs1, yofs1;
  526. X
  527. X          xsize = PLOT_CH_XSIZE * size * xrelarea;
  528. X          ysize = PLOT_CH_YSIZE * size * yrelarea;
  529. X
  530. X          yofs += 0.4;    /* middle --> botom */
  531. X          xofs1 = (xofs * xsize * cos(angle) * shape_factor -
  532. X               yofs * ysize * sin(angle));
  533. X          yofs1 = (xofs * xsize * sin(angle) * shape_factor +
  534. X               yofs * ysize * cos(angle));
  535. X          xbase = xscale(x) + xofs1;
  536. X          ybase = yscale(y) + yofs1;
  537. X
  538. X          xincr = cos(angle) * xsize * shape_factor;
  539. X          yincr = sin(angle) * ysize;
  540. X          
  541. X          /* This is how we simulate different printing directions */
  542. X          /* and character sizes: by moving to the position of every */
  543. X          /* single character one at a time */
  544. X          *(ss+1) = '\0';
  545. X          for (i=0; *ss=*s; s++,i) {
  546. X          move((int) (0.5 + xbase + i * xincr),
  547. X               (int) (0.5 + ybase + i * yincr));
  548. X          label(ss);
  549. X          i++;
  550. X          }
  551. X
  552. X          lastx = (int) (0.5 + xbase + i * xincr - xofs1);
  553. X          lasty = (int) (0.5 + ybase + i * yincr - yofs1);
  554. X          move(lastx, lasty);
  555. X      }
  556. X      break;
  557. X#endif
  558. X      default:
  559. X      invdev(); break;
  560. X      }
  561. X    return;
  562. X}
  563. X
  564. X/*
  565. X * dr_small_circle()  - draw small circle at current point.
  566. X * This routine needs the help of lastx and lasty in case of plot(3) library.
  567. X *
  568. X */
  569. Xvoid dr_draw_circle()
  570. X{
  571. X    switch (device)
  572. X      {
  573. X      case HP7475:
  574. X      sends("CI35;\n");      break;
  575. X#ifdef GL_LIB
  576. X      case SCREEN:
  577. X      n_ellipse1(100, 100);      break;
  578. X#endif
  579. X#ifdef PLOT
  580. X      case PLOTLIB:
  581. X      circle(lastx, lasty, 20);      break;
  582. X#endif
  583. X      default:
  584. X      invdev(); break;
  585. X      }
  586. X}
  587. X
  588. X
  589. X/*
  590. X * dr_finish()  - terminate the plotting
  591. X *
  592. X * This routine must be called after all plotting activity is done
  593. X * to restore the Y-cable connection so that terminal gets control
  594. X */
  595. Xint dr_finish(clean_scr)
  596. Xint clean_scr;            /* != 0 if we have clear screen */
  597. X{
  598. X    char s[20];
  599. X
  600. X    switch (device)
  601. X      {
  602. X      case HP7475:
  603. X      /* deselct pen,
  604. X       * reset Y-cable connection
  605. X       *   (<esc>.Z is ignored if not Y-cable connecton )
  606. X       */
  607. X      (void)sprintf(s, "SP;%c.Z\n", ESC);
  608. X      sends(s);
  609. X      break;
  610. X#ifdef GL_LIB
  611. X      case SCREEN:
  612. X      if (clean_scr && (strncmp(getenv("GLMODE"), "256", 3) != 0)) {
  613. X#ifdef UNIX
  614. X          FILE *fp = fopen("/dev/tty", "r");
  615. X          fgets(s, 2, fp);    /* wait for user response */
  616. X          fclose(fp);
  617. X#endif /* UNIX */
  618. X#ifdef MSDOS
  619. X          _bios_keybrd(_KEYBRD_READ); /* wait for keybrd. input forever */
  620. X#endif /* MSDOS */
  621. X      }
  622. X      {
  623. X          int status;
  624. X          status = g_finish();    /* do clean screen */
  625. X          if (status != 0)
  626. X        dr_errmsg("dr_lib(): problems with g_finish().");
  627. X      }
  628. X      break;
  629. X#endif
  630. X#ifdef PLOT
  631. X      case PLOTLIB:
  632. X      move(0,0);
  633. X      closepl();
  634. X      break;
  635. X#endif
  636. X      default:
  637. X      break;        /* call to invdev() --> recursion */
  638. X      }
  639. X      
  640. X    /* check errors, tell if any or remove error log file
  641. X     */
  642. X    if (errcount == 0 && warncount == 0)
  643. X      (void)unlink(errfilename);
  644. X    else {
  645. X    if (errcount)
  646. X      (void)fprintf(stderr, "%d error%s,",
  647. X            errcount, (errcount == 1 ? "" : "s"));
  648. X    if (warncount)
  649. X      (void)fprintf(stderr, "%d warning%s,",
  650. X            warncount, (warncount == 1 ? "" : "s"));
  651. X    (void)fprintf (stderr, " see file \"%s\".\n", errfilename);
  652. X    }
  653. X    /* return something useful
  654. X     */
  655. X    return (errcount);
  656. X}
  657. X
  658. X
  659. X/*
  660. X * dr_start  - init the plotting device
  661. X *
  662. X * This routine must be called before any plotting activity is done
  663. X * to set up the Y-cable connction so that plotter starts processing
  664. X * or in case of direct connection, open the device
  665. X */
  666. Xvoid dr_start(xlow, ylow, xhigh, yhigh, dev)
  667. Xint dev;            /* plotting device & paper size */
  668. Xfloat xlow, xhigh;        /* drawing area, relative to.. */
  669. Xfloat ylow, yhigh;        /* ..whole paper, that means: */
  670. X                /* 0.0, 0.5, 0.5, 1.0 will use */
  671. X                /* upper left quarter of paper */
  672. X{
  673. X    int p1x, p1y, p2x, p2y;
  674. X    float t1, t2;
  675. X    char s[200];
  676. X
  677. X    /* open error log file
  678. X     */
  679. X    errcount = 0;
  680. X    warncount = 0;
  681. X    if ((errfilefp = fopen(errfilename, "w")) == NULL) {
  682. X    (void)fprintf(stderr, "\nCan't open %s.  Aborting.\n", errfilename);
  683. X    exit(1);
  684. X    }
  685. X    errfile = fileno(errfilefp);
  686. X    xrelarea = xhigh - xlow;
  687. X    yrelarea = yhigh - ylow;
  688. X    shape_factor = yrelarea/xrelarea; /* back to normal 'fatness' */
  689. X    size_factor = 1.0;        /* actual size normalized to area */
  690. X
  691. X    switch (device = (dev & DEVMASK))
  692. X      {
  693. X      case HP7475:
  694. X      /* set Y-cable connection,
  695. X       *   (<esc>.Y is ignored if not Y-cable connecton )
  696. X       * init the plotter,
  697. X       * set handshake mode x-on/x-off,
  698. X       * select pen #1
  699. X       */
  700. X      (void)sprintf(s, "\n%c.Y;IN;", ESC); /* Y-connection, plotter on */
  701. X      sends(s);
  702. X      (void)sprintf(s, "%c.I80;;17:", ESC);    /* enable x-on/x-off x-on=^q */
  703. X      sends(s);
  704. X      (void)sprintf(s, "%c.N;19:\n", ESC);    /* x-off=^s */
  705. X      sends(s);
  706. X#ifdef ASK
  707. X      /* ask picture area from plotter
  708. X       * set up limits (leave some room for axis labels etc.) */
  709. X      sends("OP;");
  710. X      takes(s);
  711. X#else /* ASK */
  712. X       /* we would get one of this */
  713. X      switch (dev & SIZEMASK)
  714. X        {
  715. X        case SIZE_A:
  716. X        (void)sprintf (s, "250,596,10250,7796\n");
  717. X        sends("PS4;\n");
  718. X        break;
  719. X        case SIZE_A4:
  720. X        (void)sprintf (s, "603,521,10603,7721\n");
  721. X        sends("PS4;\n");
  722. X        break;
  723. X        case SIZE_B:
  724. X        (void)sprintf (s, "522,259,15722,10259\n");
  725. X        sends("PS3;\n");
  726. X        break;
  727. X        case SIZE_A3:
  728. X        (void)sprintf (s, "170,602,15370,10602\n");
  729. X        sends("PS3;\n");
  730. X        break;
  731. X        default:
  732. X        dr_errmsg("Invalid paper size.  Aborting.");
  733. X        (void)dr_finish();
  734. X        exit(1);
  735. X        }
  736. X#endif /* ASK */
  737. X      if ( sscanf(s, "%d,%d,%d,%d", &p1x, &p1y, &p2x, &p2y) == 4 ) {
  738. X                /* some room for labels */
  739. X          t1 = p1x + 0.05*(p2x-p1x); /* y-label */
  740. X          t2 = p2x - 0.001*(p2x-p1x); /* right margin */
  741. X          xdevicelow  = t1 + xlow * (t2 - t1);
  742. X          xdevicehigh = t1 + xhigh * (t2 - t1);
  743. X          t1 = p1y + 0.05*(p2y-p1y); /* x-label */
  744. X          t2 = p2y - 0.07*(p2y-p1y); /* name */
  745. X          ydevicelow  = t1 + ylow * (t2 - t1);
  746. X          ydevicehigh = t1 + yhigh * (t2 - t1);
  747. X      }
  748. X      else {
  749. X          dr_errmsg("Can't receive plotter dimensions.  Aborting.");
  750. X          (void) dr_finish();
  751. X          exit(1);
  752. X      }
  753. X      
  754. X      dr_set_pen(1);        /* select some pen */
  755. X      break;
  756. X#ifdef GL_LIB
  757. X      case SCREEN:
  758. X      p1x = 0;    p1y = 32767;
  759. X      p2x = 32767;    p2y = 0;
  760. X      t1 = p1x + 0.06*(p2x-p1x); /* room y-axis label */
  761. X      t2 = p2x - 0.001*(p2x-p1x); /* no room at right margin */
  762. X      xdevicelow  = t1 + xlow * (t2 - t1);
  763. X      xdevicehigh = t1 + xhigh * (t2 - t1);
  764. X      t1 = p1y + 0.10*(p2y-p1y); /* room for x-axis label */
  765. X      t2 = p2y - 0.05*(p2y-p1y); /* room fo picture's name */
  766. X      ydevicelow  = t1 + ylow * (t2 - t1);
  767. X      ydevicehigh = t1 + yhigh * (t2 - t1);
  768. X
  769. X#define ENV_MODE 0        /* from gl.h; it means that g_init() will */
  770. X                /* look operating mode in environment */
  771. X                /* variable GLMODE */
  772. X      g_init(ENV_MODE);
  773. X#undef ENV_MODE
  774. X      /* dr_set_pen(1);        /* select some pen */
  775. X      break;
  776. X#endif
  777. X
  778. X#ifdef PLOT
  779. X      case PLOTLIB:
  780. X                /* Y-cable for Tektornix? */
  781. X      p1x = 0;    p1y = 0;
  782. X      p2x = 5450;    p2y = 4095;
  783. X                /* 5% room for labels */
  784. X      t1 = p1x + 0.07*(p2x-p1x); /* y-label */
  785. X      t2 = p2x - 0.02*(p2x-p1x);; /* righ margin */
  786. X      xdevicelow  = t1 + xlow * (t2 - t1);
  787. X      xdevicehigh = t1 + xhigh * (t2 - t1);
  788. X      t1 = p1y + 0.10*(p2y-p1y); /* x-label */
  789. X      t2 = p2y - 0.05*(p2y-p1y); /* name */
  790. X      ydevicelow  = t1 + ylow * (t2 - t1);
  791. X      ydevicehigh = t1 + yhigh * (t2 - t1);
  792. X
  793. X      openpl();
  794. X      space(0,0,4096,4096);
  795. X      erase();
  796. X      break;
  797. X#endif
  798. X      default:
  799. X      invdev(); break;
  800. X      }
  801. X    
  802. X    /* check coordinate position legality
  803. X     */
  804. X    if (xlow < -0.0001 || xhigh > 1.0001 ||
  805. X    ylow < -0.0001 || yhigh > 1.0001) {
  806. X    dr_errmsg("Illegal x/y low/high position.  Aborting.");
  807. X    (void)dr_finish();
  808. X    exit(1);
  809. X    }
  810. X    return;
  811. X}
  812. X
  813. X
  814. X/* 
  815. X * dr_xgrid  - draw x grid 
  816. X *
  817. X * Draw grid lines parallel to y-axis.  When argument n == 0, makes
  818. X * lines at every tic-mark, n == 1 makes one grid line between every
  819. X * tic mark etc.  To leave grid lines away, just don't call this.
  820. X */
  821. Xvoid dr_xgrid(n)
  822. Xint n;                /* number of grid lines */
  823. X                /* between tic-marks */
  824. X{
  825. X    int i;
  826. X    int x, y1, y2;        /* temps for grid line positions */
  827. X    int nlines;            /* number of grid lines to draw */
  828. X    char s[200];
  829. X
  830. X    /* check interval
  831. X     */
  832. X    if (n < 1) {
  833. X    dr_errmsg("Invalid x-grid interval, using 1");
  834. X    n = 1;
  835. X    }
  836. X
  837. X    /* how many lines we have?
  838. X     */
  839. X    nlines = (int) (n*(xuserhigh-xuserlow)/xuserincr - 0.5);
  840. X
  841. X     switch (device)
  842. X      {
  843. X      case HP7475:
  844. X      /*  select absolute moving
  845. X       */
  846. X      sends("PA;\n");
  847. X#ifdef SLOW
  848. X      if (slow) {
  849. X      }
  850. X#endif      
  851. X      /* draw desired number of lines, sawing up and down
  852. X       */
  853. X      y1 = yscale(yuserlow);
  854. X      y2 = yscale(yuserhigh);
  855. X      for (i=1; i<=nlines; i++) {
  856. X                /* go up */
  857. X          x = xscale(i*xuserincr/n+xuserlow);
  858. X          (void)sprintf(s, "PU%d,%d;PD%d,%d;", x, y1, x, y2);
  859. X          sends(s);
  860. X                /* go down */
  861. X          if (++i <= nlines) {
  862. X          x = xscale(i*xuserincr/n+xuserlow);
  863. X          (void)sprintf(s, "PU%d,%d;PD%d,%d;\n", x, y2, x, y1);
  864. X          sends(s);
  865. X          }
  866. X      }
  867. X      
  868. X      /* lift pen
  869. X       */
  870. X      sends("PU;\n");
  871. X      break;
  872. X#ifdef GL_LIB
  873. X      case SCREEN:
  874. X      y1 = yscale(yuserlow);
  875. X      y2 = yscale(yuserhigh);
  876. X      for (i=1; i<=nlines; i++) {
  877. X          x = xscale(i*xuserincr/n+xuserlow);
  878. X          n_line(x,y1, x,y2);
  879. X      }
  880. X      break;
  881. X#endif
  882. X#ifdef PLOT
  883. X      case PLOTLIB:
  884. X      y1 = yscale(yuserlow);
  885. X      y2 = yscale(yuserhigh);
  886. X      for (i=1; i<=nlines; i++) {
  887. X          x = xscale(i*xuserincr/n+xuserlow);
  888. X          line(x,y1, x,y2);
  889. X      }
  890. X      break;
  891. X#endif
  892. X      default:
  893. X      invdev(); break;
  894. X      }
  895. X}
  896. X
  897. X
  898. X/* 
  899. X * dr_ygrid  - draw y grid 
  900. X *
  901. X * See dr_xgrid().
  902. X */
  903. Xvoid dr_ygrid(n)
  904. Xint n;
  905. X{
  906. X    int i;
  907. X    int nlines;            /* number of lines */
  908. X    char s[200];
  909. X    int x1, x2, y;
  910. X
  911. X    /* check interval
  912. X     */
  913. X    if (n < 1) {
  914. X    dr_errmsg("Invalid y-grid interval, using 1");
  915. X    n = 1;
  916. X    }
  917. X
  918. X    /* how many lines do we have?
  919. X     */
  920. X    nlines = (int) (n*(yuserhigh-yuserlow)/yuserincr - 0.5);
  921. X
  922. X    switch (device)
  923. X      {
  924. X      case HP7475:
  925. X      /* select absolute moving
  926. X       */
  927. X      sends("PA;\n");
  928. X      
  929. X      /* draw desired number of lines, sawing right and left
  930. X       */
  931. X      x1 = xscale(xuserlow);
  932. X      x2 = xscale(xuserhigh);
  933. X      for (i=1; i<=nlines; i++) {
  934. X                /* go right */
  935. X          y = yscale(yuserlow+i*yuserincr/n);
  936. X          (void)sprintf(s, "PU%d,%d;PD%d,%d;", x1, y, x2, y);
  937. X          sends(s);
  938. X                /* go left */
  939. X          if (++i <= nlines) {
  940. X          y = yscale(yuserlow+i*yuserincr/n);
  941. X          (void)sprintf(s, "PU%d,%d;PD%d,%d;", x2, y, x1, y);
  942. X          sends(s);
  943. X          }
  944. X          sends("\n");
  945. X      }
  946. X      
  947. X      /* lift pen
  948. X       */
  949. X      sends("PU;\n");
  950. X      break;
  951. X#ifdef GL_LIB
  952. X      case SCREEN:
  953. X      x1 = xscale(xuserlow);
  954. X      x2 = xscale(xuserhigh);
  955. X      for (i=1; i<=nlines; i++) {
  956. X          y = yscale(i*yuserincr/n+yuserlow);
  957. X          n_line(x1,y, x2,y);
  958. X      }
  959. X      break;
  960. X#endif
  961. X#ifdef PLOT
  962. X      case PLOTLIB:
  963. X      x1 = xscale(xuserlow);
  964. X      x2 = xscale(xuserhigh);
  965. X      for (i=1; i<=nlines; i++) {
  966. X          y = yscale(i*yuserincr/n+yuserlow);
  967. X          line(x1,y, x2,y);
  968. X      }
  969. X      break;
  970. X#endif
  971. X      default:
  972. X      invdev(); break;
  973. X      }
  974. X}
  975. X
  976. X
  977. X/* 
  978. X * dr_area_def  - establish x and y axis 
  979. X *
  980. X * [xy]low    lower left corner
  981. X * [xy]high   upper right corner
  982. X * [xy]incr   increment of tic-marks
  983. X * no_axes    flag, != 0 means don't draw axes
  984. X *
  985. X * Coordinate values will be printed at every tic-mark, so useful
  986. X * values for incr is such that (high-low)/incr will be some small
  987. X * integer.  With functions dr_xgrid() and dr_ygrid() it is possible to
  988. X * draw grid lines also in between these tic-marcs.
  989. X */
  990. Xvoid dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes)
  991. Xfloat xlow, xincr, xhigh;
  992. Xfloat ylow, yincr, yhigh;
  993. Xint no_axes;
  994. X{
  995. X    int i;
  996. X    char units[30];        /* place for units */
  997. X    char s[200];
  998. X    float x, y;
  999. X    int ix, iy, nx, ny;
  1000. X
  1001. X    /* set the globals
  1002. X     */
  1003. X    xuserlow = xlow;   xuserhigh = xhigh;   xuserincr = xincr;
  1004. X    yuserlow = ylow;   yuserhigh = yhigh;   yuserincr = yincr;
  1005. X    xfactor = (xdevicehigh - xdevicelow) / (xuserhigh - xuserlow);
  1006. X    yfactor = (ydevicehigh - ydevicelow) / (yuserhigh - yuserlow) ;
  1007. X
  1008. X    /* check legality,
  1009. X     * abort on error
  1010. X     */
  1011. X    if ((xincr == 0.0) ||
  1012. X    (xuserlow == xuserhigh) ||
  1013. X    ((xuserhigh-xuserlow)*xincr < 0.0)) {
  1014. X    dr_errmsg("x-axis defined improperly. Aborting.");
  1015. X    (void)dr_finish();
  1016. X    exit(1);
  1017. X    }
  1018. X    if ((yincr == 0.0) ||
  1019. X    (yuserlow == yuserhigh) ||
  1020. X    ((yuserhigh-yuserlow)*yincr < 0.0)) {
  1021. X    dr_errmsg("y-axis defined improperly. Aborting.");
  1022. X    (void)dr_finish();
  1023. X    exit(1);
  1024. X    }
  1025. X    if (no_axes)
  1026. X      return;
  1027. X    
  1028. X    switch (device)
  1029. X      {
  1030. X      case HP7475:
  1031. X
  1032. X      /* draw box
  1033. X       * --------
  1034. X       */
  1035. X      
  1036. X      /* select absolute plotting mode,
  1037. X       * lift pen,
  1038. X       * go to lower left corner
  1039. X       */
  1040. X      (void)sprintf(s,"PA;PU%d,%d;\n",
  1041. X            xscale(xlow), yscale(ylow));
  1042. X      sends(s);
  1043. X      
  1044. X      /* draw x-axis with x-tick marks
  1045. X       */
  1046. X      
  1047. X      (void)sprintf(s, "TL%.1f,%.1f;\n", 0.5*xrelarea, 0.5*yrelarea);
  1048. X      sends(s);
  1049. X      for (nx=0, x = xlow;
  1050. X           x < xhigh + xincr/100.0;
  1051. X           x += xincr, nx++) {
  1052. X          (void)sprintf(s, "PD%d,%d;XT;\n", xscale(x), yscale(ylow));
  1053. X          sends(s);
  1054. X      }
  1055. X      (void)sprintf(s, "PD%d,%d;\n", xscale(xhigh), yscale(ylow));
  1056. X      sends(s);
  1057. X      
  1058. X      /* draw y-axis with y-tick marks
  1059. X       */
  1060. X      (void)sprintf(s, "PU%d,%d;\n",
  1061. X            xscale(xlow), yscale(ylow));
  1062. X      sends(s);
  1063. X      for (ny=0, y = ylow;
  1064. X           y < yhigh + yincr/100.0;
  1065. X           y += yincr, ny++) {
  1066. X          (void)sprintf(s, "PD%d,%d;YT;\n", xscale(xlow), yscale(y));
  1067. X          sends(s);
  1068. X      }
  1069. X      (void)sprintf(s, "PD%d,%d;\n", xscale(xlow), yscale(yhigh));
  1070. X      sends(s);
  1071. X
  1072. X      /* outer borders of the box
  1073. X       */
  1074. X      (void)sprintf(s, "PU%d,%d;PD%d,%d,%d,%d;PU\n",
  1075. X            xscale(xlow), yscale(yhigh),
  1076. X            xscale(xhigh), yscale(yhigh),
  1077. X            xscale(xhigh), yscale(ylow));
  1078. X      sends(s);
  1079. X      break;
  1080. X#ifdef GL_LIB
  1081. X#define GL_TIC_SIZE 200
  1082. X      case SCREEN:
  1083. X      iy = yscale(ylow);
  1084. X      n_movepen(xscale(xlow), iy);
  1085. X
  1086. X      for (nx=0, x = xlow;
  1087. X           x < xhigh + xincr/100.0;
  1088. X           x += xincr, nx++) {
  1089. X          ix = xscale(x);
  1090. X          n_draw(ix, iy);
  1091. X          n_line(ix, iy+GL_TIC_SIZE, ix, iy-GL_TIC_SIZE);
  1092. X          n_movepen(ix, iy);
  1093. X      }
  1094. X      n_draw(xscale(xhigh), iy);
  1095. X
  1096. X      /* draw y-axis with y-tick marks
  1097. X       */
  1098. X      ix = xscale(xlow);
  1099. X      n_movepen(ix, yscale(ylow));
  1100. X      for (ny=0, y = ylow;
  1101. X           y < yhigh + yincr/100.0;
  1102. X           y += yincr, ny++) {
  1103. X          iy = yscale(y);
  1104. X          n_draw(ix, iy);
  1105. X          n_line(ix+GL_TIC_SIZE, iy, ix-GL_TIC_SIZE, iy);
  1106. X          n_movepen(ix, iy);
  1107. X      }
  1108. X      n_draw(ix, yscale(yhigh));
  1109. X      
  1110. X      /* outer borders of the box
  1111. X       */
  1112. X      n_movepen(xscale(xlow), yscale(yhigh));
  1113. X      n_draw(xscale(xhigh), yscale(yhigh));
  1114. X      n_draw(xscale(xhigh), yscale(ylow));
  1115. X      break;
  1116. X#endif
  1117. X#ifdef PLOT
  1118. X#define PLOT_TIC_SIZE 40
  1119. X      case PLOTLIB:
  1120. X      iy = yscale(ylow);
  1121. X      move(xscale(xlow), iy);
  1122. X
  1123. X      for (nx=0, x = xlow;
  1124. X           x < xhigh + xincr/100.0;
  1125. X           x += xincr, nx++) {
  1126. X          ix = xscale(x);
  1127. X          cont(ix, iy);
  1128. X          line(ix, iy+PLOT_TIC_SIZE, ix, iy-PLOT_TIC_SIZE);
  1129. X          move(ix, iy);
  1130. X      }
  1131. X      cont(xscale(xhigh), iy);
  1132. X
  1133. X      /* draw y-axis with y-tick marks
  1134. X       */
  1135. X      ix = xscale(xlow);
  1136. X      move(ix, yscale(ylow));
  1137. X      for (ny=0, y = ylow;
  1138. X           y < yhigh + yincr/100.0;
  1139. X           y += yincr, ny++) {
  1140. X          iy = yscale(y);
  1141. X          cont(ix, iy);
  1142. X          line(ix+PLOT_TIC_SIZE, iy, ix-PLOT_TIC_SIZE, iy);
  1143. X          move(ix, iy);
  1144. X      }
  1145. X      cont(ix, yscale(yhigh));
  1146. X      
  1147. X      /* outer borders of the box
  1148. X       */
  1149. X      move(xscale(xlow), yscale(yhigh));
  1150. X      cont(xscale(xhigh), yscale(yhigh));
  1151. X      cont(xscale(xhigh), yscale(ylow));
  1152. X      break;
  1153. X#endif
  1154. X      default:
  1155. X      invdev(); break;
  1156. X      }
  1157. X
  1158. X    
  1159. X    /* put y-units
  1160. X     */
  1161. X    for (i=ny-1; i>=0; i--) {
  1162. X     (void)sprintf(units, "%g", ylow + i * yincr);
  1163. X     dr_put_text(xlow, ylow+i*yincr,
  1164. X            -strlen(units)/2.0, -1.3, -M_PI_2, 1.0, units);
  1165. X    }
  1166. X
  1167. X    /* put x-units
  1168. X     */
  1169. X    for (i=0; i<nx; i++) {
  1170. X    (void)sprintf(units, "%g", xlow + i * xincr);
  1171. X    dr_put_text(xlow+i*xincr, ylow,
  1172. X            -strlen(units)/2.0, -1.3, 0.0, 1.0, units);
  1173. X    }
  1174. X    return;
  1175. X}
  1176. X
  1177. X/*
  1178. X * linetypes
  1179. X *
  1180. X */
  1181. X#ifdef GL_LIB
  1182. Xstatic long gl_line_types[] = {    /* 76543210765432107654321076543210 */
  1183. X    0xf0000000L,        /* ====............................ */
  1184. X    0xffff0000L,        /* ================................ */
  1185. X    0xffffff00L,        /* ========================........ */
  1186. X    0xffffff18L,        /* ========================...==... */
  1187. X    0xfffff0f0L,        /* ====================....====.... */
  1188. X    0xfffff39cL,        /* ====================..===..===.. */
  1189. X    0xffffffffL,        /* ================================ */
  1190. X    0x66666666L,        /* ==..==..==..==..==..==..==..==.. */
  1191. X    0xf8f8f8f8L,        /* =====...=====...=====...=====... */
  1192. X    0xffffff00L,        /* ========================........ */
  1193. X    0xfc30fc30L };        /* ======....==....======....==.... */
  1194. X#define DEF_GL_TYPE 7        /* this will produce continous line */
  1195. X#endif /* GL_PLOT */
  1196. X#ifdef PLOT
  1197. Xstatic char *plot_line_types[] = {
  1198. X    "dotted",            /* 1 */
  1199. X    "longdashed",        /* 2 */
  1200. X    "shortdashed",        /* 3 */
  1201. X    "dotdashed",        /* 4 */
  1202. X    "solid",            /* 5 */
  1203. X    "solid",            /* 6 */
  1204. X    "solid" };            /* 7 */
  1205. X#define DEF_PLOT_TYPE 7        /* this will produce continous line */
  1206. X#endif /* PLOT */
  1207. X
  1208. Xint dr_set_ltype(linetype)
  1209. Xint linetype;
  1210. X{
  1211. X    char s[40];
  1212. X    int old_val = old_linetype;
  1213. X
  1214. X    switch (device)
  1215. X      {
  1216. X      case HP7475:
  1217. X      if (linetype < 0 || linetype > 6) {
  1218. X          linetype = 7;
  1219. X          sends("LT;");
  1220. X      }
  1221. X      else {
  1222. X          (void)sprintf(s, "LT%d;", linetype);
  1223. X          sends(s);
  1224. X      }
  1225. X      break;
  1226. X#ifdef GL_LIB
  1227. X      case SCREEN:
  1228. X      if (linetype < 1 ||
  1229. X          linetype > (sizeof(gl_line_types) / sizeof(gl_line_types[0]))) {
  1230. X           sprintf (s, "Invalid linetype: %d", linetype);
  1231. X           dr_errmsg(s);
  1232. X           linetype = DEF_GL_TYPE;
  1233. X       }
  1234. X      g_style(gl_line_types[linetype-1]);
  1235. X      break;
  1236. X#endif
  1237. X#ifdef PLOT        
  1238. X      case PLOTLIB:
  1239. X      if (linetype < 1 ||
  1240. X          linetype > (sizeof(plot_line_types) /
  1241. X              sizeof(plot_line_types[0]))) {
  1242. X           sprintf (s, "Invalid linetype: %d", linetype);
  1243. X           dr_errmsg(s);
  1244. X           linetype = DEF_PLOT_TYPE;
  1245. X       }
  1246. X      linemod(plot_line_types[linetype-1]);
  1247. X      break;
  1248. X#endif
  1249. X      default:
  1250. X      invdev(); break;
  1251. X      }
  1252. X    old_linetype = linetype;
  1253. X    return old_val;
  1254. X}
  1255. X
  1256. X/*
  1257. X * xscale  - scaling in horizontal directon
  1258. X *
  1259. X * convert user x-coordinate to physical device x-coordinate
  1260. X */
  1261. Xstatic int xscale(x)
  1262. Xfloat x;
  1263. X{
  1264. X    int temp;
  1265. X    char s[60];
  1266. X
  1267. X    /* calculate it
  1268. X     */
  1269. X    temp = (int) ((x - xuserlow) * xfactor + xdevicelow + 0.5);
  1270. X    /* check, if it is good
  1271. X     */
  1272. X    if ((temp >= -32768) && (temp <= 32767))
  1273. X      return (temp);
  1274. X
  1275. X    /* when not good make report,
  1276. X     * return something
  1277. X     */
  1278. X    (void)sprintf(s, "x-value out of range: %f", x);
  1279. X    dr_warnmsg(s);
  1280. X    return (int) (xdevicelow + 0.5);
  1281. X}
  1282. X
  1283. X
  1284. X/*
  1285. X * yscale  - scaling in vertical directon
  1286. X *
  1287. X * convert user y-coordinate to physical device y-coordinate
  1288. X */
  1289. Xstatic int yscale(y)
  1290. Xfloat y;
  1291. X{
  1292. X    int temp;
  1293. X    char s[60];
  1294. X
  1295. X    /* calculate it
  1296. X     */
  1297. X    temp = (int) ((y - yuserlow) * yfactor + ydevicelow + 0.5);
  1298. X
  1299. X    /* check, if it is good
  1300. X     */
  1301. X    if ((temp >= -32768) && (temp <= 32767))
  1302. X      return (temp);
  1303. X
  1304. X    /* when not good make report,
  1305. X     * return something
  1306. X     */
  1307. X    (void)sprintf(s, "y-value out of range: %f", y);
  1308. X    dr_warnmsg(s);
  1309. X    return (int) (ydevicelow + 0.5);
  1310. X}
  1311. X
  1312. Xstatic void invdev()
  1313. X{
  1314. X    dr_errmsg("Invalid plotting device.");
  1315. X    (void)dr_finish();
  1316. X    exit(1);
  1317. X}
  1318. X
  1319. X
  1320. X/*
  1321. X * dr_errmsg  - send a string to error output
  1322. X *
  1323. X */
  1324. Xvoid dr_errmsg(s)
  1325. Xchar *s;
  1326. X{
  1327. X    char *p = s + strlen(s);
  1328. X    if (p != s) p--;
  1329. X    while ((p != s) && (*p == '\n')) /* strip the newlines */
  1330. X      *(p--) = '\0';
  1331. X    fprintf(errfilefp, "dr_lib error: %s\n", s);
  1332. X    errcount++;
  1333. X    return;
  1334. X}
  1335. X
  1336. X
  1337. X/*
  1338. X * warnmsg  - send a string to error output
  1339. X *
  1340. X */
  1341. Xvoid dr_warnmsg(s)
  1342. Xchar *s;
  1343. X{
  1344. X    char *p = s + strlen(s);
  1345. X    if (p != s) p--;
  1346. X    while ((p != s) && (*p == '\n')) *(p--) = '\0';
  1347. X    fprintf(errfilefp, "Warning: %s\n", s);
  1348. X    warncount++;
  1349. X    return;
  1350. X}
  1351. X
  1352. X
  1353. X/*
  1354. X * sends  - send something to plotting device
  1355. X *
  1356. X */
  1357. Xstatic void sends(s)
  1358. Xchar *s;
  1359. X{
  1360. X    (void)printf("%s", s);
  1361. X}
  1362. X
  1363. X#ifdef ASK
  1364. X/*
  1365. X * takes  - take a string from plotter (to read plotter coordinates)
  1366. X *
  1367. X */
  1368. X#include <signal.h>
  1369. X#include <setjmp.h>
  1370. X
  1371. Xjmp_buf sjbuf;
  1372. Xint (*savAlrm)();        /* save incomming alarm function */
  1373. X
  1374. Xstatic int timerh()        /* timer interrupt handler */
  1375. X{
  1376. X    longjmp(sjbuf, 1);
  1377. X}
  1378. X
  1379. Xstatic void takes(s)
  1380. Xchar *s;
  1381. X{
  1382. X#ifdef YCABLE
  1383. X    savAlrm = signal(SIGALRM,timerh);
  1384. X    alarm(2);            /* give time to wake up */
  1385. X    if (setjmp(sjbuf)) {
  1386. X    alarm(0);
  1387. X    signal(SIGALRM,savAlrm); /* cancel timer */
  1388. X    (void)dr_finish();
  1389. X    (void)fprintf(stderr, "\n\7Timeout reading stdin.  Aborting.\n");
  1390. X    exit(1);
  1391. X    }
  1392. X    gets(s);
  1393. X    alarm(0);
  1394. X    signal(SIGALRM,savAlrm);    /* cancel timer */
  1395. X#else
  1396. X    /* do it yorself */
  1397. X#endif
  1398. X}
  1399. X#endif /* ASK */
  1400. END_OF_FILE
  1401. if test 31312 -ne `wc -c <'dr_lib.c'`; then
  1402.     echo shar: \"'dr_lib.c'\" unpacked with wrong size!
  1403. fi
  1404. # end of 'dr_lib.c'
  1405. fi
  1406. if test -f 'draw.c' -a "${1}" != "-c" ; then 
  1407.   echo shar: Will not clobber existing file \"'draw.c'\"
  1408. else
  1409. echo shar: Extracting \"'draw.c'\" \(17080 characters\)
  1410. sed "s/^X//" >'draw.c' <<'END_OF_FILE'
  1411. X/*
  1412. X
  1413. XCopyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
  1414. X
  1415. X     This program is free software; you can redistribute it and/or modify
  1416. X     it under the terms of the GNU General Public License as published by
  1417. X     the Free Software Foundation; version 1.
  1418. X
  1419. X     This program is distributed in the hope that it will be useful,
  1420. X     but WITHOUT ANY WARRANTY; without even the implied warranty of
  1421. X     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1422. X     the file "License for more details
  1423. X
  1424. X     You should have received a copy of the GNU General Public License
  1425. X     along with this program; if not, write to the Free Software
  1426. X     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1427. X
  1428. X
  1429. X */
  1430. X
  1431. X/* Description:
  1432. X *  Non-interactive user interface program to provide interface between
  1433. X *  device manipulation subroutines and user supplied command files.
  1434. X *  This program will accept all kinds of command line arguments and
  1435. X *  pseudo comments mixed in between the data lines.  See the man page.
  1436. X *
  1437. X *  The good thing about this program is that it will accept infinite
  1438. X *  amount of input data points; they are not stored, but processed one
  1439. X *  at a time.
  1440. X */
  1441. Xstatic char *RCS_id =
  1442. X  "$Id: draw.c,v 2.7 89/12/08 14:00:39 jta Exp Locker: jta $";
  1443. X
  1444. X#include <stdio.h>
  1445. X#ifdef MSDOS
  1446. X#include <stdlib.h>
  1447. X#endif /* MSDOS */
  1448. X#include <string.h>
  1449. X#include <sys/types.h>
  1450. X#include <time.h>
  1451. X#include <math.h>
  1452. X#include <signal.h>
  1453. X#ifndef MSDOS
  1454. X#include <sys/inode.h>
  1455. X#include <sys/file.h>
  1456. X#endif
  1457. X#include <string.h>
  1458. X#include "dr_lib.h"
  1459. X
  1460. Xdouble strtod();
  1461. X
  1462. Xchar *myname;
  1463. Xfloat xlowl = 0.0;        /* relative plotting area on paper */
  1464. Xfloat ylowl = 0.0;
  1465. Xfloat xhighr= 1.0;
  1466. Xfloat yhighr = 1.0;
  1467. X
  1468. Xfloat xlow = -1.0;        /* x axis range */
  1469. Xfloat xincr = 0.5;
  1470. Xfloat xhigh = 1.0;
  1471. Xint xgrid_n = 0;
  1472. Xchar *xlabel_text = NULL;
  1473. X
  1474. Xfloat ylow = -1.0;        /* y axis range */
  1475. Xfloat yincr = 0.5;
  1476. Xfloat yhigh = 1.0;
  1477. Xint ygrid_n = 0;
  1478. Xchar *ylabel_text = NULL;
  1479. X
  1480. Xstatic float x, y;        /* current point, needs to be */
  1481. X                /* remembered, eg. when relative text is */
  1482. X                /* inserted by #$texthere */
  1483. Xchar *name_text = NULL;        /* name of picture */
  1484. Xint pennum = 1;
  1485. Xint penup = 1;
  1486. Xint no_axes = 0;
  1487. Xint init_done = 0;
  1488. Xint dateflag = 0;
  1489. Xint linetype = 7;        /* default for solid linetype */
  1490. Xfloat text_angle = 0.0;        /* radians */
  1491. Xfloat text_size = 1.0;        /* text size factor */
  1492. Xfloat text_shape = 1.0;        /* text shape factor */
  1493. Xint cset = 0;            /* char set, default is US Ascii */
  1494. Xint continuous = 1;        /* continuous line / discrete points */
  1495. X                /* 0 = discontinous */
  1496. Xchar marker = '*';        /* default marker char in discontinous mode */
  1497. Xchar informat[200] = "%f %f";    /* default input data line format */
  1498. Xint reversed = 0;        /* != 0 means input is y before x  */
  1499. Xint absolute = 0;        /* != 0 when 'absolute' coordinates are */
  1500. X                /* to be processed */
  1501. Xfloat xabs_origin = 0.0;    /* origin of 'absolute' mode data points */
  1502. Xfloat yabs_origin = 0.0;
  1503. X
  1504. Xint device = HP7475 | SIZE_A4;
  1505. X
  1506. Xstatic int setmode();
  1507. Xstatic int labelpic();
  1508. Xstatic void doit();
  1509. Xstatic void setdevice();
  1510. Xextern void exit();
  1511. X
  1512. Xstatic void (*old_int_handler)();
  1513. Xstatic void new_int_handler();
  1514. Xstatic void fatal();
  1515. Xstatic void usage();
  1516. X
  1517. X#define PUT_TEXT(x,y,xofs,yofs,text) \
  1518. X      dr_put_text((x), (y), (xofs), (yofs), text_angle, 1.0, (text))
  1519. X#define PUT_X_TEXT(x,y,text) \
  1520. X      dr_put_text((x), (y), -(float)strlen(text), -2.0, 0.0, 1.4, (text))
  1521. X#define PUT_Y_TEXT(x,y,text) \
  1522. X      dr_put_text((x), (y), 0.0, -2.0, -M_PI_2, 1.4, (text))
  1523. X#define PUT_N_TEXT(x,y,text) \
  1524. X      dr_put_text((x), (y), -(float)strlen(text)/2.0, 0.4, 0.0, 2.0, (text))
  1525. X
  1526. Xmain(argc, argv)
  1527. Xint argc;
  1528. Xchar *argv[];
  1529. X{
  1530. X    int c;
  1531. X    extern char *optarg;
  1532. X    extern int optind, opterr;
  1533. X    char *opts = "a:bc:df:g:hl:m:n:p:s:S:t:x:X:y:Y:v";
  1534. X
  1535. X    FILE *fp;
  1536. X
  1537. X    myname = *argv;
  1538. X    setdevice(getenv("DRAWDEV"));
  1539. X
  1540. X
  1541. X    while ((c = getopt(argc, argv, opts)) != -1) {
  1542. X    switch (c) {
  1543. X    case 'a':
  1544. X        if (sscanf(optarg, "%f,%f,%f,%f",
  1545. X               &xlowl, &ylowl, &xhighr, &yhighr) != 4)
  1546. X          fatal("invalid plotting area definition: ", optarg);
  1547. X        break;
  1548. X    case 'b': no_axes++; break;
  1549. X    case 'c': cset = atoi(optarg); break;
  1550. X    case 'd': dateflag++; break;
  1551. X    case 'f':
  1552. X        /* input lines are : "-- -- y -- -- x -- --"
  1553. X         * (dashes indicate fields, that we are not interested in)
  1554. X         * and we want to plot y=f(x), so we specify option
  1555. X         * "-f 6,3" (fields are numbered from 1...)
  1556. X         */
  1557. X        {
  1558. X        int xcol, ycol;
  1559. X        if (sscanf(optarg, "%d,%d", &xcol, &ycol) != 2)
  1560. X          fatal("invalid input format definition: %s", optarg);
  1561. X        if (xcol == ycol)
  1562. X          fatal("invalid input format definition: %s", optarg);
  1563. X        if (xcol > ycol) {
  1564. X            int temp = xcol;
  1565. X            reversed++;
  1566. X            xcol = ycol;
  1567. X            ycol = temp;
  1568. X        }
  1569. X        ycol -= xcol;
  1570. X        informat[0] = '\0';
  1571. X        while (--xcol)
  1572. X          (void)strcat(informat, "%*f ");
  1573. X        (void)strcat(informat, "%f ");
  1574. X        while (--ycol)
  1575. X          (void)strcat(informat, "%*f ");
  1576. X        (void)strcat(informat, "%f");
  1577. X        }
  1578. X        break;
  1579. X    case 'g':
  1580. X        if (sscanf(optarg, "%d,%d", &xgrid_n, &ygrid_n) != 2)
  1581. X          fatal("invalid grid spec.: ", optarg);
  1582. X        break;
  1583. X    case 'h': case '?':
  1584. X        usage(); break;
  1585. X    case 'l':
  1586. X        if (sscanf(optarg, "%d", &linetype) != 1)
  1587. X          fatal("invalid line type:", optarg);
  1588. X        break;        /* draw axes before setting it! */
  1589. X    case 'm':
  1590. X        continuous = 0;
  1591. X        if (sscanf(optarg, "%1s", &marker) != 1)
  1592. X          fatal ("no marker found.", "\0");
  1593. X        break;
  1594. X    case 'n':
  1595. X        name_text = optarg; break;
  1596. X    case 'p':
  1597. X        if (sscanf(optarg, "%d", &pennum) != 1)
  1598. X          fatal("invalid pen:", optarg);
  1599. X        if ((pennum > 6) || (pennum < 1))
  1600. X          pennum = 1;
  1601. X        break;
  1602. X    case 's':
  1603. X        if (sscanf(optarg, "%f", &text_size) != 1)
  1604. X          fatal("invalid text size: ", optarg);
  1605. X        break;
  1606. X    case 'S':
  1607. X        if (sscanf(optarg, "%f", &text_shape) != 1)
  1608. X          fatal("invalid text shape: ", optarg);
  1609. X        break;
  1610. X    case 't': setdevice(optarg); break;
  1611. X    case 'x':
  1612. X        if (sscanf(optarg, "%f,%f,%f",
  1613. X               &xlow, &xincr, &xhigh) != 3)
  1614. X          fatal("invalid x range: ", optarg);
  1615. X        break;
  1616. X    case 'X':
  1617. X        xlabel_text = optarg; break;
  1618. X    case 'y':
  1619. X        if (sscanf(optarg, "%f,%f,%f",
  1620. X               &ylow, &yincr, &yhigh) != 3)
  1621. X          fatal("invalid y range: ", optarg);
  1622. X        break;
  1623. X    case 'Y':
  1624. X        ylabel_text = optarg; break;
  1625. X    case 'v':
  1626. X        fprintf(stderr, "%s\n", RCS_id);
  1627. X        exit (0);
  1628. X    default:
  1629. X        exit(1);
  1630. X    }
  1631. X    }
  1632. X    argc -= optind;
  1633. X    argv += optind;
  1634. X
  1635. X    old_int_handler = signal (SIGINT, new_int_handler);
  1636. X
  1637. X    /*
  1638. X     * Options have been taken, start the work.  Initializations will be
  1639. X     * done just before first data point is used...  This is jippo to
  1640. X     * make it possible to give coordinate specifications from inside
  1641. X     * the data....
  1642. X     */
  1643. X    if (argc == 0)        /* no files, take points from stdin */
  1644. X      doit(stdin);
  1645. X    else {            /* take points from all files */
  1646. X    for ( ; argc; argc--, argv++) {
  1647. X        if (NULL == (fp = fopen(*argv, "r"))) {
  1648. X        perror(*argv);
  1649. X        continue;
  1650. X        }
  1651. X        doit(fp);
  1652. X        fclose(fp);
  1653. X    }
  1654. X    }
  1655. X    if (init_done)
  1656. X      return(dr_finish(1) ? 1 : 0); /* 1 == error(s) */
  1657. X    else
  1658. X      return 2;            /* nothing was done! */
  1659. X}
  1660. X
  1661. X
  1662. X/* gl_plot will set int handler at its initialization time, and restore
  1663. X   what it saw there previously, and finally it will
  1664. X   kill(SIGINT,getpid()).  This is what we are going to do, too, so that
  1665. X   OUR caller can clean ITS data stuctures etc.
  1666. X*/
  1667. Xstatic void new_int_handler() {
  1668. X    (void)dr_finish(0);
  1669. X    signal (SIGINT, old_int_handler);
  1670. X    kill (getpid(), SIGINT);    /* zap my self */
  1671. X    sleep(1);
  1672. X    exit(3);            /* if that is not enough */
  1673. X}
  1674. X
  1675. X
  1676. Xstatic void do_initializations()
  1677. X{
  1678. X    init_done++;        /* remember it is done */
  1679. X    dr_start(xlowl, ylowl, xhighr, yhighr, device);
  1680. X    if (cset != 0) dr_set_cset(cset);
  1681. X    dr_set_size(text_size);
  1682. X    dr_set_shape(text_shape);
  1683. X    dr_set_pen(pennum);
  1684. X    dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes);
  1685. X    if (!no_axes) {
  1686. X    if (xgrid_n) dr_xgrid(xgrid_n);
  1687. X    if (ygrid_n) dr_ygrid(ygrid_n);
  1688. X    }
  1689. X    if (xlabel_text) PUT_X_TEXT(xhigh, ylow, xlabel_text);
  1690. X    if (ylabel_text) PUT_Y_TEXT(xlow, yhigh, ylabel_text);
  1691. X    if (name_text) PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, name_text);
  1692. X    if (dateflag) putdate(dateflag);
  1693. X    dr_set_ltype(linetype);
  1694. X}
  1695. X
  1696. Xstatic void setdevice(s)
  1697. Xchar *s;
  1698. X{
  1699. X    if (s == NULL) return;
  1700. X    if      (!strcmp(s,"a4")) device = (HP7475 | SIZE_A4);
  1701. X    else if (!strcmp(s,"a3")) device = (HP7475 | SIZE_A3);
  1702. X    else if (!strcmp(s,"a"))  device = (HP7475 | SIZE_A);
  1703. X    else if (!strcmp(s,"b"))  device = (HP7475 | SIZE_B);
  1704. X#ifdef GL_LIB
  1705. X    else if (!strcmp(s,"ega")) device = SCREEN;
  1706. X#endif
  1707. X#ifdef PLOT
  1708. X    else if (!strcmp(s,"plot")) device = PLOTLIB;
  1709. X#endif
  1710. X#ifdef TEK
  1711. X    else if (!strcmp(s,"tek"))
  1712. X      fatal("Sorry,", "Tek4010 not yet.");
  1713. X#endif
  1714. X    else fatal("Unsupported plotting device", s);
  1715. X}
  1716. X  
  1717. Xstatic void doit(fp)
  1718. XFILE *fp;
  1719. X{
  1720. X#define LINESIZE 512
  1721. X    char buf[LINESIZE+1], *p;
  1722. X    char emsg[200];
  1723. X    int lineno = 0;
  1724. X    
  1725. X    while (1) {
  1726. X    if (NULL == fgets(buf, LINESIZE, fp)) /* EOF */
  1727. X      return;
  1728. X
  1729. X    lineno++;
  1730. X    for (p=buf; *p; p++)    /* skip white space */
  1731. X      if (strchr(" \t",*p) == NULL)
  1732. X        break;
  1733. X    if (*p == '\n')
  1734. X      continue;
  1735. X
  1736. X    if (*p == '#') {
  1737. X        if (setmode(p+1)) {
  1738. X        sprintf(emsg, "Invalid pseudo comment line (%d): %s",
  1739. X            lineno, buf);
  1740. X        if (init_done)
  1741. X          dr_errmsg(emsg);
  1742. X        else
  1743. X          write(2, emsg, strlen(emsg));
  1744. X        }
  1745. X        continue;
  1746. X    }
  1747. X                /* now we expect data lines, */
  1748. X                /* initializations must be done by now */
  1749. X    if (!init_done) do_initializations();
  1750. X
  1751. X    if (sscanf(p, informat, &x, &y) != 2) {
  1752. X        sprintf(emsg, "Invalid data line (%d): %s", lineno, buf);
  1753. X        dr_errmsg(emsg);
  1754. X        continue;
  1755. X    }
  1756. X    if (reversed) {
  1757. X        float temp = x;
  1758. X        x = y;
  1759. X        y = temp;
  1760. X    }
  1761. X    if (absolute) {
  1762. X        x = xlow + (xabs_origin + x) * (xhigh - xlow);
  1763. X        y = ylow + (yabs_origin + y) * (yhigh - ylow);
  1764. X    }
  1765. X    /* this needs to be fixed: reversed directions not handled! */
  1766. X    if (x < xlow || x > xhigh || y < ylow || y > yhigh) {
  1767. X        sprintf (emsg, "point out of range at line (%d): %s",
  1768. X             lineno, buf);
  1769. X        dr_warnmsg(emsg);
  1770. X    }
  1771. X    if (continuous) {
  1772. X        dr_goto(x, y, penup);
  1773. X        penup = 0;
  1774. X    }
  1775. X    else {
  1776. X        dr_put_mark(x, y, marker);
  1777. X    }
  1778. X    }
  1779. X}
  1780. X
  1781. Xstatic void remember(to, from)    /* copy string to safe place, put its */
  1782. X                /* addr into `*to' */
  1783. Xchar **to, *from;
  1784. X{
  1785. X#ifndef MSDOS
  1786. X    extern char *malloc();
  1787. X#endif
  1788. X    *to = malloc(strlen(from)+1);
  1789. X    strcpy(*to, from);
  1790. X}
  1791. X
  1792. X                /* handle '#<something>' lines */
  1793. Xstatic int setmode(s)        /* return 0 on success, != when trouble */
  1794. Xchar *s;
  1795. X{
  1796. X    for (; *s; s++)        /* skip white space */
  1797. X      if (strchr(" \t",*s) == NULL)
  1798. X    break;
  1799. X    if (*s++ != '$')        /* only '$' causes action */
  1800. X      return 0;
  1801. X
  1802. X    for (; *s; s++)        /* skip white space */
  1803. X      if (strchr(" \t",*s) == NULL)
  1804. X    break;
  1805. X    
  1806. X    if (!strncmp (s, "absolute", 8)) {
  1807. X    absolute = 1;
  1808. X    if (sscanf(s+8, "%f,%f", &xabs_origin, &yabs_origin) == 2)
  1809. X      return 0;
  1810. X    xabs_origin = 0.0;
  1811. X    yabs_origin = 0.0;
  1812. X    return 1;
  1813. X    }
  1814. X
  1815. X    if (!strncmp (s, "endabsolute", 11)) {
  1816. X    absolute = 0;
  1817. X    return 0;
  1818. X    }
  1819. X
  1820. X    if (!strncmp (s,"penup",5)) {
  1821. X    penup = 1;
  1822. X    return 0;
  1823. X    }
  1824. X
  1825. X
  1826. X    if (!strncmp(s, "include", 7)) {
  1827. X    FILE *fp;
  1828. X    char *p;
  1829. X    
  1830. X    for (s+=8; *s; s++)    /* skip whitespace */
  1831. X      if (strchr(" \t",*s) == NULL)
  1832. X         break;
  1833. X    for (p=s; *p; p++)
  1834. X       if (strchr(" \t\n",*s) != NULL)
  1835. X         break;
  1836. X     *(p-1) = '\0';        /* put terminator */
  1837. X     
  1838. X     if (NULL == (fp = fopen(s, "r"))) {
  1839. X         perror(p);
  1840. X         return 1;
  1841. X     }
  1842. X     doit(fp);        /* recursive call */
  1843. X     fclose(fp);
  1844. X     return 0;
  1845. X    }
  1846. X    if (!strncmp (s, "cset", 4)) {
  1847. X    int csetnum = 0;
  1848. X    if (sscanf(s+4, "%d", &csetnum) != 1)
  1849. X      return 1;
  1850. X    if (!init_done) do_initializations();
  1851. X    dr_set_cset(csetnum);
  1852. X    return 0;
  1853. X    }
  1854. X
  1855. X    if (!strncmp (s, "pen", 3)) {
  1856. X    if (sscanf(s+3, "%d", &pennum) != 1)
  1857. X      return 1;
  1858. X    if (!init_done) do_initializations();
  1859. X    dr_set_pen(pennum);
  1860. X    return 0;
  1861. X    }
  1862. X
  1863. X    if (!strncmp (s, "ltype", 5)) {
  1864. X    int linetype = 1;
  1865. X    if (sscanf(s+5, "%d", &linetype) != 1)
  1866. X      return 1;
  1867. X    if (!init_done) do_initializations();
  1868. X    dr_set_ltype(linetype);
  1869. X    return 0;
  1870. X    }
  1871. X
  1872. X    if (!strncmp(s, "mark", 4)) {
  1873. X    s += 4;
  1874. X    while (1) {
  1875. X        marker = *s++;
  1876. X        if (strchr(" \t", marker) == NULL)
  1877. X          break;
  1878. X    }
  1879. X    continuous = (strchr (" \n\r\t", marker) != NULL);
  1880. X    return 0;
  1881. X    }
  1882. X
  1883. X    if (!strncmp(s, "date",   4)) {
  1884. X    if (dateflag)
  1885. X      return 1;
  1886. X    dateflag = 1;
  1887. X    if (init_done)
  1888. X      putdate(1);
  1889. X    return 0;
  1890. X    }
  1891. X    if (!strncmp(s, "time",   4)) {
  1892. X    if (dateflag)
  1893. X      return 1;
  1894. X    dateflag = 2;
  1895. X    if (init_done)
  1896. X      putdate(2);
  1897. X    return 0;
  1898. X    }
  1899. X
  1900. X    if (!strncmp(s, "xlabel", 6)) {
  1901. X    if (xlabel_text) return 1;
  1902. X    s += 7;            /* skip one space/separator */
  1903. X    s[strlen(s)-1] = '\0';    /* drop newline */
  1904. X    if (!init_done) {
  1905. X        remember(&xlabel_text, s);
  1906. X        return 0;
  1907. X    }
  1908. X    PUT_X_TEXT(xhigh, ylow, s);
  1909. X    xlabel_text = myname;    /* some char-pointer that has non NULL */
  1910. X                /* value, so that we remember this */
  1911. X    penup = 1;
  1912. X    return 0;
  1913. X    }
  1914. X
  1915. X    if (!strncmp(s, "ylabel", 6)) {
  1916. X    if (ylabel_text) return 1;
  1917. X    s += 7;
  1918. X    s[strlen(s)-1] = '\0';
  1919. X    if (!init_done) {
  1920. X        remember(&ylabel_text, s);
  1921. X        return 0;
  1922. X    }
  1923. X    PUT_Y_TEXT(xlow, yhigh, s);
  1924. X    ylabel_text = myname;
  1925. X    penup = 1;
  1926. X    return 0;
  1927. X    }
  1928. X
  1929. X    if (!strncmp(s, "name", 4)) {
  1930. X    if (name_text) return 1;
  1931. X    s += 5;            /* skip the space */
  1932. X    s[strlen(s)-1] = '\0';    /* drop newline */
  1933. X    if (!init_done) {
  1934. X        remember(&name_text, s);
  1935. X        return 0;
  1936. X    }
  1937. X    PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, s);
  1938. X    name_text = myname;    
  1939. X    penup = 1;
  1940. X    return 0;
  1941. X    }
  1942. X
  1943. X    if (!strncmp(s, "xrange", 6)) {
  1944. X    if (sscanf(s+6, "%f,%f,%f", &xlow, &xincr, &xhigh) != 3)
  1945. X      return 1;
  1946. X    return 0;
  1947. X    }
  1948. X
  1949. X    if (!strncmp(s, "yrange", 6)) {
  1950. X    if (sscanf(s+6, "%f,%f,%f", &ylow, &yincr, &yhigh) != 3)
  1951. X      return 1;
  1952. X    return 0;
  1953. X    }
  1954. X
  1955. X    if (!strncmp(s, "area", 4)) {
  1956. X    if (sscanf(s+4, "%f,%f,%f,%f",
  1957. X           &xlowl, &ylowl, &xhighr, &yhighr) != 4)
  1958. X      return 1;
  1959. X    return 0;
  1960. X    }
  1961. X
  1962. X    if (!strncmp(s, "grid", 4)) {
  1963. X    if (sscanf(s+4, "%d,%d", &xgrid_n, &ygrid_n) != 2)
  1964. X      return 1;
  1965. X    return 0;
  1966. X    }
  1967. X
  1968. X    if (!strncmp(s, "noaxes", 6)) {
  1969. X    no_axes++;
  1970. X    return 0;
  1971. X    }
  1972. X
  1973. X    if (!strncmp(s, "init", 4)) {
  1974. X    if (!init_done) do_initializations();
  1975. X    return 0;
  1976. X    }
  1977. X
  1978. X    if (!strncmp(s, "size", 4)) {
  1979. X    if (sscanf(s+4, "%f", &text_size) != 1)
  1980. X      return 1;
  1981. X    if (init_done)
  1982. X      dr_set_size(text_size);
  1983. X    return 0;
  1984. X    }
  1985. X
  1986. X    if (!strncmp(s, "shape", 5)) {
  1987. X    if (sscanf(s+5, "%f", &text_shape) != 1)
  1988. X      return 1;
  1989. X    if (init_done)
  1990. X      dr_set_shape(text_shape);
  1991. X    return 0;
  1992. X    }
  1993. X
  1994. X    if (!strncmp(s, "direction", 9)) {
  1995. X    float xx;
  1996. X
  1997. X    if (sscanf(s+9, "%f", &xx) != 1)
  1998. X      return 1;
  1999. X    text_angle = xx;
  2000. X    return 0;
  2001. X    }
  2002. X
  2003. X    if (!strncmp(s, "text",   4)) return (labelpic(s+4, 0, 0));
  2004. X    if (!strncmp(s, "alabel", 6)) return (labelpic(s+6, 0, 1));
  2005. X    if (!strncmp(s, "rlabel", 6)) return (labelpic(s+6, 1, 1));
  2006. X
  2007. X                /* other options are errors */
  2008. X    return 1;
  2009. X}
  2010. X
  2011. Xstatic int labelpic(s, rel, conn)
  2012. Xchar *s;
  2013. Xint rel, conn;
  2014. X{
  2015. X    float xx, yy;
  2016. X    char *s1;
  2017. X    int old_linetype;
  2018. X
  2019. X    if (!init_done) do_initializations();
  2020. X
  2021. X    old_linetype = dr_set_ltype(7); /* set solid line */
  2022. X    xx = strtod(s, &s1);
  2023. X    if (s1 == s) return 1;
  2024. X    s = s1+1;
  2025. X    yy = strtod(s, &s1);
  2026. X    if (s1 == s) return 1;
  2027. X    s1++;            /* skip the separator */
  2028. X    s1[strlen(s1)-1] = '\0';
  2029. X    if (rel) {
  2030. X    xx += x;
  2031. X    yy += y;
  2032. X    }
  2033. X    PUT_TEXT(xx, yy, 0.0, 0.15, s1);
  2034. X    if (conn) {
  2035. X    dr_goto(xx, yy, 0);
  2036. X    dr_goto(x, y, 0);
  2037. X    dr_draw_circle();
  2038. X    }
  2039. X    else
  2040. X      penup = 1;
  2041. X    (void) dr_set_ltype(old_linetype);
  2042. X    return 0;
  2043. X}
  2044. X
  2045. Xint putdate(flag)
  2046. Xint flag;
  2047. X{
  2048. X    struct tm *timp;
  2049. X    long clk;
  2050. X    char buf1[40], buf2[20];
  2051. X
  2052. X    if (time(&clk) < 0) {
  2053. X    (void) sprintf (buf1, "time() failed.");
  2054. X    (void) dr_errmsg(buf1);
  2055. X    return 1;
  2056. X    }
  2057. X    timp = localtime(&clk);
  2058. X    sprintf(buf1, "%d/%d/%d",
  2059. X        timp->tm_mday, timp->tm_mon+1, timp->tm_year + 1900);
  2060. X    if (flag > 1)
  2061. X      sprintf(buf2, " %02d:%02d:%02d",
  2062. X          timp->tm_hour, timp->tm_min, timp->tm_sec);
  2063. X    else
  2064. X      buf2[0] = '\0';
  2065. X    strcat(buf1, buf2);
  2066. X    PUT_TEXT(xhigh, yhigh, -(float)strlen(buf1), 0.7, buf1);
  2067. X    penup = 1;
  2068. X    return 0;
  2069. X}
  2070. X
  2071. X
  2072. Xvoid fatal(s1, s2)
  2073. Xchar *s1, *s2;
  2074. X{
  2075. X    fprintf (stderr,"%s: Fatal error: %s %s\n", myname, s1, s2);
  2076. X    exit(1);
  2077. X}
  2078. X
  2079. Xstatic char *utbl[] = {
  2080. X    "-a xlo,ylo,xhi,yhi\tspecify relative plot area on paper",
  2081. X    "-b\t\t\tdon't draw axes",
  2082. X    "-c num\t\t\tchoose character set `num'",
  2083. X    "-d\t\t\tinclude date (time) stamp",
  2084. X    "-f c1,c2\t\tuse these columns of input, higher is for y",
  2085. X    "-g xgrid,ygrid\t\tspecify x&y grids",
  2086. X    "-h\t\t\tgive this stuff",
  2087. X    "-l\t\t\tlinetype",
  2088. X    "-m marker\t\tspecify marker & discontinous mode",
  2089. X    "-n text\t\tname the picture",
  2090. X    "-p num\t\t\tspecify pen number",
  2091. X#ifdef GL_LIB
  2092. X    "-t target\t\tspecify device: `ega', `a3', `a4' etc. Defaults from env.",
  2093. X#else
  2094. X    "-t target\t\tspecify device: `a3', `a4' etc. Defaults from env.",
  2095. X#endif
  2096. X    "-x|y low,incr,high\tspecify axis range",
  2097. X    "-X|Y text\t\taxis label",
  2098. X    "-v\t\t\tprint version ID",
  2099. X    "Most (all?) of these may also be given inside the data, look for manual",
  2100. X    NULL
  2101. X};
  2102. X
  2103. Xvoid usage()
  2104. X{
  2105. X    register char **p;
  2106. X    printf ("usage: \"%s [opts] [file ...]\"\n", myname);
  2107. X    for (p=utbl; *p; p++)
  2108. X      (void)printf (" %s\n", *p);
  2109. X    exit(0);
  2110. X}
  2111. END_OF_FILE
  2112. if test 17080 -ne `wc -c <'draw.c'`; then
  2113.     echo shar: \"'draw.c'\" unpacked with wrong size!
  2114. fi
  2115. # end of 'draw.c'
  2116. fi
  2117. echo shar: End of archive 2 \(of 2\).
  2118. cp /dev/null ark2isdone
  2119. MISSING=""
  2120. for I in 1 2 ; do
  2121.     if test ! -f ark${I}isdone ; then
  2122.     MISSING="${MISSING} ${I}"
  2123.     fi
  2124. done
  2125. if test "${MISSING}" = "" ; then
  2126.     echo You have unpacked both archives.
  2127.     rm -f ark[1-9]isdone
  2128. else
  2129.     echo You still need to unpack the following archives:
  2130.     echo "        " ${MISSING}
  2131. fi
  2132. ##  End of shell archive.
  2133. exit 0
  2134.